package org.apache.lucene.distributed.index;
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.distributed.RMI;
import org.apache.lucene.distributed.index.IndexManagerService.IndexInfo;
import org.apache.lucene.distributed.index.IndexService.IndexListener;

/**
 * Client for accessing a LuceneServer.  LuceneIndex adds an IndexListener to the 
 * IndexService so that it always has the most up to date SearchableService.  
 * On the server side when a reopen occurs the IndexListener is notified
 * of the new SearchableService.  
 *
 */
public class LuceneClient {
  public final RMI rmi;
  public final IndexManagerService indexManagerService;
  
  public LuceneClient(InetSocketAddress addr, RMI rmi) throws IOException {
    this.rmi = rmi;
    indexManagerService = (IndexManagerService)rmi.getProxy("indexManagerService", IndexManagerService.class, 1l, addr, false);
  }
  
  /**
   * Creates a LuceneIndex object for an IndexService obtained from the indexManagerService
   * @param indexService
   * @return
   * @throws Exception
   */
  public LuceneIndex getIndex(IndexService indexService) throws Exception {
    return new LuceneIndex(indexService);
  }
  
  /**
   * Wraps an IndexService and manages the IndexListener
   *
   */
  public class LuceneIndex implements IndexListener {
    public IndexService indexService;
    private volatile SearchableService searchableService;
    private List<IndexListener> indexListeners = new ArrayList<IndexListener>();
    
    public LuceneIndex(IndexService indexService) throws Exception {
      this.indexService = indexService;
      IndexInfo indexInfo = indexService.getIndexInfo();
      InetSocketAddress addr = rmi.getInetSocketAddress();
      rmi.getServer().addService("luceneclient."+indexInfo.name+"."+addr.getHostName()+":"+addr.getPort()+".indexlistener", this, true);
      searchableService = indexService.reopen();
      indexService.registerIndexListener(this);
    }
    
    public void addIndexListener(IndexListener indexListener) {
      indexListeners.add(indexListener);
    }
    
    public SearchableService getSearchable() {
      return searchableService;
    }
    
    public void newSearchable(SearchableService searchableService) throws Exception {
      this.searchableService = searchableService;
      for (IndexListener indexListener : indexListeners) {
        indexListener.newSearchable(searchableService);
      }
    }
  }
}
